package module.map.utils
{
	import drongo.desktop.utils.CollisionsHelp;
	import drongo.model.propertys.ArrayProperty;
	import drongo.model.values.CollectionValue;

	import flash.geom.Point;

	import module.map.model.Propertys;
	import drongo.model.propertys.NumberProperty;

	public class PathUtils
	{
		private static var negativePath:Vector.<Number> = new Vector.<Number>();
		private static var vectorList:Vector.<Number> = new Vector.<Number>();

		private static var lastPoint:Point = new Point();
		private static var lastPointValue:CollectionValue;
		private static var currentPoint:Point = new Point();
		private static var currentPointValue:CollectionValue;
		private static var nextPointValue:CollectionValue;
		private static var nextPoint:Point = new Point();

		private static var tempPoint1:Point = new Point();
		private static var tempPoint2:Point = new Point();
		private static var tempPoint0:Point = new Point();
		private static var v0:Point = new Point();
		private static var v1:Point = new Point();
		private static var v2:Point = new Point();

		public function PathUtils()
		{
		}

		/**
		 * 边缘点转导航网格
		 */
		public static function Edge2Nav(edge:Vector.<Number>, out:Vector.<Number>):void
		{
			var count:uint = edge.length * 0.5;
			for (var index:int = 0; index < count; index++)
			{
				out.push(edge[index * 2], edge[index * 2 + 1]);
				if (1 <= index && index < count - 1)
				{
					out.push(edge[index * 2], edge[index * 2 + 1]);
				}
			}
		}

		public static function GetPath1(path:CollectionValue, navWidth:Number, navHeight:Number, result:Array, mirrorY:Boolean = false):void
		{
			var x:Number = navWidth + path.Get(Propertys.X).GetValue();
			var y:Number = navHeight + path.Get(Propertys.Y).GetValue();
			var points:ArrayProperty = path.Get(Propertys.POINTS) as ArrayProperty;
			var count:uint = points.length;
			var index:Number = 0;
			for (index = 0; index < count; index++)
			{
				currentPointValue = points.GetAt(index) as CollectionValue;
				currentPoint.x = currentPointValue.Get(Propertys.X).GetValue();
				currentPoint.y = currentPointValue.Get(Propertys.Y).GetValue();
				if (mirrorY)
				{
					result.push(x + currentPoint.x, -(y + currentPoint.y));
				}
				else
				{
					result.push(x + currentPoint.x, y + currentPoint.y);
				}
			}
		}

		public static function GetPath2(path:CollectionValue, navWidth:Number, navHeight:Number, result:Array, pathCount:uint, mirrorY:Boolean = false):void
		{
			var x:Number = navWidth + path.Get(Propertys.X).GetValue();
			var y:Number = navHeight + path.Get(Propertys.Y).GetValue();
			var points:ArrayProperty = path.Get(Propertys.POINTS) as ArrayProperty;
			var count:uint = points.length;
			var index:Number = 0;
			vectorList.length = 0;

			if (pathCount <= 1)
			{
				var arr:Array = [];
				for (index = 0; index < count; index++)
				{
					currentPointValue = points.GetAt(index) as CollectionValue;
					currentPoint.x = currentPointValue.Get(Propertys.X).GetValue();
					currentPoint.y = currentPointValue.Get(Propertys.Y).GetValue();
					if (mirrorY)
					{
						arr.push(x + currentPoint.x, -(y + currentPoint.y));
					}
					else
					{
						arr.push(x + currentPoint.x, y + currentPoint.y);
					}
				}
				result.push(arr);
				return;
			}
			if (pathCount % 2 == 0)
			{
				throw new Error("路径数量必须是奇数");
			}
			// 一半的等分数量
			var otherCount:uint = (pathCount - 1) * 0.5;

			for (var i:int = 0; i < pathCount; i++)
			{
				result.push([]);
			}

			// 先计算法线向量
			var normals:Vector.<Number> = new Vector.<Number>();
			for (index = 0; index < count; index++)
			{
				GetVerticalVector(points, index, normals, v0);
			}

			var len:int = points.length;
			var pointWidth:Number = 0;
			var normal:Point = v0;
			for (var pointIndex:int = 0; pointIndex < len; pointIndex++)
			{
				for (var pathIndex:int = 1; pathIndex <= otherCount; pathIndex++)
				{
					currentPointValue = points.GetAt(pointIndex) as CollectionValue;
					currentPoint.x = currentPointValue.Get(Propertys.X).GetValue();
					currentPoint.y = currentPointValue.Get(Propertys.Y).GetValue();
					pointWidth = currentPointValue.Get(Propertys.WIDTH).GetValue() * 0.5 / otherCount;
					// 法线
					normal.x = normals[pointIndex * 2];
					normal.y = normals[pointIndex * 2 + 1];
					normal.normalize(pathIndex * pointWidth);
					// 正方向的点
					if (mirrorY)
					{
						result[pathIndex - 1].push(x + Math.floor(currentPoint.x + normal.x), -(y + Math.floor(currentPoint.y + normal.y)));
					}
					else
					{
						result[pathIndex - 1].push(x + Math.floor(currentPoint.x + normal.x), y + Math.floor(currentPoint.y + normal.y));
					}

					// 反向的点
					normal.normalize(-(pathIndex * pointWidth));
					if (mirrorY)
					{
						result[otherCount + 1 + pathIndex - 1].push(x + Math.floor(currentPoint.x + normal.x), -(y + Math.floor(currentPoint.y + normal.y)));
					}
					else
					{
						result[otherCount + 1 + pathIndex - 1].push(x + Math.floor(currentPoint.x + normal.x), y + Math.floor(currentPoint.y + normal.y));
					}
					// 路径本身
					if (mirrorY)
					{
						result[otherCount].push(x + currentPoint.x, -(y + currentPoint.y));
					}
					else
					{
						result[otherCount].push(x + currentPoint.x, y + currentPoint.y);
					}
				}
			}
		}

		private static function GetVerticalVector(points:ArrayProperty, index:Number, records:Vector.<Number>, result:Point):void
		{
			currentPointValue = points.GetAt(index) as CollectionValue;
			currentPoint.x = currentPointValue.Get(Propertys.X).GetValue();
			currentPoint.y = currentPointValue.Get(Propertys.Y).GetValue();

			if (index == points.length - 1)
			{
				lastPointValue = points.GetAt(index - 1) as CollectionValue;
				lastPoint.x = lastPointValue.Get(Propertys.X).GetValue();
				lastPoint.y = lastPointValue.Get(Propertys.Y).GetValue();
				// 求出垂直向量
				CollisionsHelp.VerticalVector2(currentPoint, lastPoint, v0);

				// 上一个向量
				v1.x = records[(index - 1) * 2];
				v1.y = records[(index - 1) * 2 + 1];
				v0.normalize(1);
				v1.normalize(1);
				// 向量插值，求中间向量
				v0.x = (v1.x + v0.x) * 0.5;
				v0.y = (v1.y + v0.y) * 0.5;
				records.push(v0.x, v0.y);
			}
			else
			{
				nextPointValue = points.GetAt(index + 1) as CollectionValue;
				nextPoint.x = nextPointValue.Get(Propertys.X).GetValue();
				nextPoint.y = nextPointValue.Get(Propertys.Y).GetValue();
				// 求出垂直向量
				CollisionsHelp.VerticalVector2(nextPoint, currentPoint, v0);
				if (index == 0)
				{
					records.push(v0.x, v0.y);
					return;
				}
				// 上一个向量
				v1.x = records[(index - 1) * 2];
				v1.y = records[(index - 1) * 2 + 1];
				v0.normalize(1);
				v1.normalize(1);
				// 向量插值，求中间向量
				v0.x = (v1.x + v0.x) * 0.5;
				v0.y = (v1.y + v0.y) * 0.5;
				records.push(v0.x, v0.y);
			}
		}

		/**
		 * 获取路径
		 */
		public static function GetPath(path:CollectionValue, navWidth:Number, navHeight:Number, result:Array, pathCount:uint, mirrorY:Boolean = false):void
		{
			var x:Number = navWidth + path.Get(Propertys.X).GetValue();
			var y:Number = navHeight + path.Get(Propertys.Y).GetValue();
			var points:ArrayProperty = path.Get(Propertys.POINTS) as ArrayProperty;
			var count:uint = points.length;
			var w:Number, j:int;
			var index:Number = 0;
			vectorList.length = 0;

			if (pathCount <= 1)
			{
				var arr:Array = [];
				for (index = 0; index < count; index++)
				{
					currentPointValue = points.GetAt(index) as CollectionValue;
					currentPoint.x = currentPointValue.Get(Propertys.X).GetValue();
					currentPoint.y = currentPointValue.Get(Propertys.Y).GetValue();
					if (mirrorY)
					{
						arr.push(x + currentPoint.x, -(y + currentPoint.y));
					}
					else
					{
						arr.push(x + currentPoint.x, y + currentPoint.y);
					}
				}
				result.push(arr);
				return;
			}
			if (pathCount % 2 == 0)
			{
				throw new Error("路径数量必须是奇数");
			}
			// 一半的等分数量
			var otherCount:uint = (pathCount - 1) * 0.5;

			for (var i:int = 0; i < pathCount; i++)
			{
				result.push([]);
			}

			for (index = 0; index < count; index++)
			{
				currentPointValue = points.GetAt(index) as CollectionValue;
				currentPoint.x = currentPointValue.Get(Propertys.X).GetValue();
				currentPoint.y = currentPointValue.Get(Propertys.Y).GetValue();

				// 起点
				if (index == 0)
				{
					nextPointValue = points.GetAt(index + 1) as CollectionValue;
					nextPoint.x = nextPointValue.Get(Propertys.X).GetValue();
					nextPoint.y = nextPointValue.Get(Propertys.Y).GetValue();

					// 求出垂直向量
					CollisionsHelp.VerticalVector2(nextPoint, currentPoint, v0);

					w = currentPointValue.Get(Propertys.WIDTH).GetValue() * 0.5 / otherCount;

					for (j = 1; j <= otherCount; j++)
					{
						v0.normalize(j * w);
						// 正方向的点
						if (mirrorY)
						{
							result[j - 1].push(x + Math.floor(currentPoint.x + v0.x), -(y + Math.floor(currentPoint.y + v0.y)));
						}
						else
						{
							result[j - 1].push(x + Math.floor(currentPoint.x + v0.x), y + Math.floor(currentPoint.y + v0.y));
						}

						// 反向的点
						v0.normalize(-(j * w));
						if (mirrorY)
						{
							result[otherCount + 1 + j - 1].push(x + Math.floor(currentPoint.x + v0.x), -(y + Math.floor(currentPoint.y + v0.y)));
						}
						else
						{
							result[otherCount + 1 + j - 1].push(x + Math.floor(currentPoint.x + v0.x), y + Math.floor(currentPoint.y + v0.y));
						}
					}
					// 路径本身
					if (mirrorY)
					{
						result[otherCount].push(x + currentPoint.x, -(y + currentPoint.y));
					}
					else
					{
						result[otherCount].push(x + currentPoint.x, y + currentPoint.y);
					}

					// 记录当前向量，用于下一个点的计算
					v0.normalize(1);
					vectorList.push(v0.x, v0.y);
				}
				else if (index == count - 1)
				{
					lastPointValue = points.GetAt(index - 1) as CollectionValue;
					lastPoint.x = lastPointValue.Get(Propertys.X).GetValue();
					lastPoint.y = lastPointValue.Get(Propertys.Y).GetValue();

					// 求出垂直向量
					CollisionsHelp.VerticalVector2(currentPoint, lastPoint, v0);

					w = currentPointValue.Get(Propertys.WIDTH).GetValue() * 0.5 / otherCount;

					for (j = 1; j <= otherCount; j++)
					{
						v0.normalize(j * w);
						// 正方向的点
						if (mirrorY)
						{
							result[j - 1].push(x + Math.floor(currentPoint.x + v0.x), -(y + Math.floor(currentPoint.y + v0.y)));
						}
						else
						{
							result[j - 1].push(x + Math.floor(currentPoint.x + v0.x), y + Math.floor(currentPoint.y + v0.y));
						}

						// 反向的点
						v0.normalize(-(j * w));
						if (mirrorY)
						{
							result[otherCount + 1 + j - 1].push(x + Math.floor(currentPoint.x + v0.x), -(y + Math.floor(currentPoint.y + v0.y)));
						}
						else
						{
							result[otherCount + 1 + j - 1].push(x + Math.floor(currentPoint.x + v0.x), y + Math.floor(currentPoint.y + v0.y));
						}
					}
					// 路径本身
					if (mirrorY)
					{
						result[otherCount].push(x + currentPoint.x, -(y + currentPoint.y));
					}
					else
					{
						result[otherCount].push(x + currentPoint.x, y + currentPoint.y);
					}

					// 记录当前向量，用于下一个点的计算
					v0.normalize(1);
					vectorList.push(v0.x, v0.y);
				}
				else
				{
					nextPointValue = points.GetAt(index + 1) as CollectionValue;
					nextPoint.x = nextPointValue.Get(Propertys.X).GetValue();
					nextPoint.y = nextPointValue.Get(Propertys.Y).GetValue();
					// 求出垂直向量
					CollisionsHelp.VerticalVector2(nextPoint, currentPoint, v0);

					// 上一个向量
					v1.x = vectorList[(index - 1) * 2];
					v1.y = vectorList[(index - 1) * 2 + 1];
					v0.normalize(1);
					v1.normalize(1);
					// 向量插值，求中间向量
					v2.x = (v1.x + v0.x) * 0.5;
					v2.y = (v1.y + v0.y) * 0.5;

					w = currentPointValue.Get(Propertys.WIDTH).GetValue() * 0.5 / otherCount;

					for (j = 1; j <= otherCount; j++)
					{
						v2.normalize(j * w);
						// 正方向的点
						if (mirrorY)
						{
							result[j - 1].push(x + Math.floor(currentPoint.x + v2.x), -(y + Math.floor(currentPoint.y + v2.y)));
						}
						else
						{
							result[j - 1].push(x + Math.floor(currentPoint.x + v2.x), y + Math.floor(currentPoint.y + v2.y));
						}

						// 反向的点
						v2.normalize(-(j * w));
						if (mirrorY)
						{
							result[otherCount + 1 + j - 1].push(x + Math.floor(currentPoint.x + v2.x), -(y + Math.floor(currentPoint.y + v2.y)));
						}
						else
						{
							result[otherCount + 1 + j - 1].push(x + Math.floor(currentPoint.x + v2.x), y + Math.floor(currentPoint.y + v2.y));
						}
					}
					// 路径本身
					if (mirrorY)
					{
						result[otherCount].push(x + currentPoint.x, -(y + currentPoint.y));
					}
					else
					{
						result[otherCount].push(x + currentPoint.x, y + currentPoint.y);
					}

					// 记录当前向量，用于下一个点的计算
					v2.normalize(1);
					vectorList.push(v2.x, v2.y);
				}
			}
		}

		/**
		 * 获取边缘点
		 */
		public static function GetEdge(pw:Number, ph:Number, path:CollectionValue, out:Object, isClosed:Boolean = true, toGlobal:Boolean = false, mirrorY:Boolean = false):void
		{
			var x:Number = path.Get(Propertys.X).GetValue() + pw;
			var y:Number = path.Get(Propertys.Y).GetValue() + ph;

			var points:ArrayProperty = path.Get(Propertys.POINTS) as ArrayProperty;

			out.length = negativePath.length = 0;

			var count:uint = points.length;

			var w:Number = 20;

			vectorList.length = 0;

			for (var index:int = 0; index < count; index++)
			{
				currentPointValue = points.GetAt(index) as CollectionValue;
				currentPoint.x = currentPointValue.Get(Propertys.X).GetValue();
				currentPoint.y = currentPointValue.Get(Propertys.Y).GetValue();
				// 起点
				if (index == 0)
				{
					nextPointValue = points.GetAt(index + 1) as CollectionValue;
					nextPoint.x = nextPointValue.Get(Propertys.X).GetValue();
					nextPoint.y = nextPointValue.Get(Propertys.Y).GetValue();
					w = currentPointValue.Get(Propertys.WIDTH).GetValue();

					// 求出垂直向量
					CollisionsHelp.VerticalVector2(nextPoint, currentPoint, v0);

					v0.normalize(w * 0.5);

					vectorList.push(v0.x, v0.y);
					if (toGlobal)
					{
						// 正方向的点
						out.push(x + currentPoint.x + v0.x);
						if (mirrorY)
						{
							out.push(-(y + currentPoint.y + v0.y));
						}
						else
						{
							out.push(y + currentPoint.y + v0.y);
						}
						// 反方向的点(由于最后这个数组会反过来所以y,x)
						if (mirrorY)
						{
							negativePath.push(-(y + currentPoint.y - v0.y));
						}
						else
						{
							negativePath.push(y + currentPoint.y - v0.y);
						}
						negativePath.push(x + currentPoint.x - v0.x);
					}
					else
					{
						// 正方向的点
						out.push(currentPoint.x + v0.x);
						if (mirrorY)
						{
							out.push(-(currentPoint.y + v0.y));
						}
						else
						{
							out.push(currentPoint.y + v0.y);
						}
						// 反方向的点(由于最后这个数组会反过来所以y,x)
						if (mirrorY)
						{
							negativePath.push(-(currentPoint.y - v0.y));
						}
						else
						{
							negativePath.push(currentPoint.y - v0.y);
						}
						negativePath.push(currentPoint.x - v0.x);
					}

				}
				else if (index == count - 1)
				{
					lastPointValue = points.GetAt(index - 1) as CollectionValue;
					lastPoint.x = lastPointValue.Get(Propertys.X).GetValue();
					lastPoint.y = lastPointValue.Get(Propertys.Y).GetValue();

					// 求出垂直向量
					CollisionsHelp.VerticalVector2(currentPoint, lastPoint, v0);
					w = currentPointValue.Get(Propertys.WIDTH).GetValue();
					v0.normalize(w * 0.5);

					vectorList.push(v0.x, v0.y);

					if (toGlobal)
					{
						// 正方向的点
						out.push(x + currentPoint.x + v0.x);
						if (mirrorY)
						{
							out.push(-(y + currentPoint.y + v0.y));
						}
						else
						{
							out.push(y + currentPoint.y + v0.y);
						}
						// 反方向的点(由于最后这个数组会反过来所以y,x)
						if (mirrorY)
						{
							negativePath.push(-(y + currentPoint.y - v0.y));
						}
						else
						{
							negativePath.push(y + currentPoint.y - v0.y);
						}
						negativePath.push(x + currentPoint.x - v0.x);
					}
					else
					{
						// 正方向的点
						out.push(currentPoint.x + v0.x);
						if (mirrorY)
						{
							out.push(-(currentPoint.y + v0.y));
						}
						else
						{
							out.push(currentPoint.y + v0.y);
						}
						// 反方向的点(由于最后这个数组会反过来所以y,x)
						if (mirrorY)
						{
							negativePath.push(-(currentPoint.y - v0.y));
						}
						else
						{
							negativePath.push(currentPoint.y - v0.y);
						}
						negativePath.push(currentPoint.x - v0.x);
					}
				}
				else
				{
					nextPointValue = points.GetAt(index + 1) as CollectionValue;
					nextPoint.x = nextPointValue.Get(Propertys.X).GetValue();
					nextPoint.y = nextPointValue.Get(Propertys.Y).GetValue();
					// 求出垂直向量
					CollisionsHelp.VerticalVector2(nextPoint, currentPoint, v0);
					w = currentPointValue.Get(Propertys.WIDTH).GetValue();
					// 上一个向量
					v1.x = vectorList[(index - 1) * 2];
					v1.y = vectorList[(index - 1) * 2 + 1];
					v0.normalize(1);
					v1.normalize(1);
					// 向量插值，求中间向量
					v2.x = (v1.x + v0.x) * 0.5;
					v2.y = (v1.y + v0.y) * 0.5;

					vectorList.push(v2.x, v2.y);

					v2.normalize(w * 0.5);

					if (toGlobal)
					{
						// 正方向的点
						out.push(x + currentPoint.x + v2.x);
						if (mirrorY)
						{
							out.push(-(y + currentPoint.y + v2.y));
						}
						else
						{
							out.push(y + currentPoint.y + v2.y);
						}
						// 反方向的点(由于最后这个数组会反过来所以y,x)
						if (mirrorY)
						{
							negativePath.push(-(y + currentPoint.y - v2.y));
						}
						else
						{
							negativePath.push(y + currentPoint.y - v2.y);
						}
						negativePath.push(x + currentPoint.x - v2.x);
					}
					else
					{
						// 正方向的点
						out.push(currentPoint.x + v2.x);
						if (mirrorY)
						{
							out.push(-(currentPoint.y + v2.y));
						}
						else
						{
							out.push(currentPoint.y + v2.y);
						}
						// 反方向的点(由于最后这个数组会反过来所以y,x)
						if (mirrorY)
						{
							negativePath.push(-(currentPoint.y - v2.y));
						}
						else
						{
							negativePath.push(currentPoint.y - v2.y);
						}
						negativePath.push(currentPoint.x - v2.x);
					}
				}
			}
			negativePath.reverse();
			for (var i:int = 0; i < negativePath.length; i++)
			{
				out.push(negativePath[i]);
			}
			// 闭合空间
			if (isClosed)
			{
				out.push(out[0], out[1]);
			}
		}
	}
}